#pragma once
#ifndef INPUT__MANAGER__HH__
#define INPUT__MANAGER__HH__

#include <LitPrerequisites.h>
#include <unordered_map>
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#include <Windows.h>
#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE
#elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX
#endif
namespace Lit
{
	enum KeyEnum
	{
		Key_None = 0,
		Key_A = 'A',
		Key_B = 'B',
		Key_C = 'C',
		Key_D = 'D',
		Key_E = 'E',
		Key_F = 'F',
		Key_G = 'G',
		Key_H = 'H',
		Key_I = 'I',
		Key_J = 'J',
		Key_K = 'K',
		Key_L = 'L',
		Key_M = 'M',
		Key_N = 'N',
		Key_O = 'O',
		Key_P = 'P',
		Key_Q = 'Q',
		Key_R = 'R',
		Key_S = 'S',
		Key_T = 'T',
		Key_U = 'U',
		Key_V = 'V',
		Key_W = 'W',
		Key_X = 'X',
		Key_Y = 'Y',
		Key_Z = 'Z',
		Key_0 = '0',
		Key_1 = '1',
		Key_2 = '2',
		Key_3 = '3',
		Key_4 = '4',
		Key_5 = '5',
		Key_6 = '6',
		Key_7 = '7',
		Key_8 = '8',
		Key_9 = '9',
		Key_LBracket = '[',
		Key_RBracket = '[',
		Key_LBrace = '{',
		Key_RBrace = '}',
		Key_LParenthesis = '(',
		Key_RParenthesis = ')',
		Key_Dot = '.',
		Key_SemiColon = ';',
		Key_Coma = ',',
		Key_Colon = ':',
		Key_Bar = '|',
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
		Key_Delete = VK_DELETE,
		Key_ArrowUp = VK_UP,
		Key_ArrowDown = VK_DOWN,
		Key_ArrowLeft = VK_LEFT,
		Key_ArrowRight = VK_RIGHT,
		Key_Backspace = VK_BACK,
		Key_Return = VK_RETURN,
#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE
		Key_Delete = VK_DELETE,
		Key_ArrowUp = VK_UP,
		Key_ArrowDown = VK_DOWN,
		Key_ArrowLeft = VK_LEFT,
		Key_ArrowRight = VK_RIGHT,
		Key_Backspace = VK_BACK,
		Key_Return = VK_RETURN,
		Key_Enter = VK_ENTER,
#elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX
		Key_Delete = VK_DELETE,
		Key_ArrowUp = VK_UP,
		Key_ArrowDown = VK_DOWN,
		Key_ArrowLeft = VK_LEFT,
		Key_ArrowRight = VK_RIGHT,
		Key_Backspace = VK_BACK,
		Key_Return = VK_RETURN,
#endif
		Key_Space = ' ',
		Key_Quote = '\'',
		Key_DoubleQuote = '"'
	};
	enum KeyModifier
	{
		Key_Control = VK_CONTROL,
		Key_RAlt = VK_RMENU,
		Key_LAlt = VK_LMENU,
		Key_Shift = VK_SHIFT
	};
	struct Key
	{
		KeyEnum code;
		bool	down;

		Key( KeyEnum cod=Key_None ): down(false), code(cod){}
		Key( const Key & k ) : code(k.code), down(k.down){}
			
		static bool isSpecial( KeyEnum k )
		{
			return k == Key_ArrowRight ||
				k == Key_ArrowLeft ||
				k == Key_ArrowUp ||
				k == Key_ArrowDown ||
				k == Key_Backspace ||
				k == Key_Return;
		}
		bool isSpecial( ) const
		{
			return Key::isSpecial( code );
		}
	};
	class InputSystem : public Singleton<InputSystem>
	{
		typedef std::unordered_map<KeyEnum, Key> KeyMap;
		KeyMap mKeys;
		
		InputSystem(){}
		InputSystem( const InputSystem& rk ) : mKeys( rk.mKeys ){}
		friend class Singleton<InputSystem>;
	public:
		~InputSystem(){}
		
		bool isModifierDown( KeyModifier m ) const
		{
			return (GetAsyncKeyState( (int)m ) & 0x8000);
		}
		bool isKeyDown( KeyEnum e ) const
		{
			KeyMap::const_iterator it = mKeys.find(e);
			if( it == mKeys.end() ) return false;
			return it->second.down;
		}
		bool isKeyUp( KeyEnum e ) const
		{
			return !isKeyDown(e);
		}

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
			void captureWindows(){
				for( unsigned short i=0; i<256; i++ )
				{
					KeyEnum k=KeyEnum(i);
					if( mKeys.find(k) == mKeys.end() )
						mKeys[k] = Key(k);
					mKeys[k].down = (GetAsyncKeyState((int)k)&0x8000);
				}

			}
#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE
			void captureMac(){
				for( unsigned short i=0; i<256; i++ )
				{
					KeyEnum k=KeyEnum(i);
					if( mKeys.find(k) == mKeys.end() )
						mKeys[k] = Key(k);
					mKeys[k].down = (GetAsyncKeyState((int)k)&0x8000);
				}
			}
#elif OGRE_PLATFORM == OGRE_PLATFORM_LINUX
			void captureLinux(){
				for( unsigned short i=0; i<256; i++ )
				{
					KeyEnum k=KeyEnum(i);
					if( mKeys.find(k) == mKeys.end() )
						mKeys[k] = Key(k);
					mKeys[k].down = (GetAsyncKeyState((int)k)&0x8000);
				}
			}
#endif
	};
};
#endif